import { User } from '../models/User'
import { common } from '@kit.AbilityKit'
import { relationalStore } from '@kit.ArkData';
import { SQLiteOpener } from './SQLiteOpener';
import {
  BaseDao,
  DaoMaster,
  DaoSession,
  Database,
  GlobalContext,
  Migration,
  QueryBuilder
} from '@ohos/dataorm';
import { TableBasic } from '../models/TableBasic';


const dbConfig: relationalStore.StoreConfig = {
  name: 'Demo.db',
  securityLevel: relationalStore.SecurityLevel.S1,
}

const dbVersion = 1;

export class DBService<T extends TableBasic> {
  private context: common.Context;
  private helper: SQLiteOpener;
  private daoSession: DaoSession | undefined = undefined;
  private db: Database

  protected tableDao: BaseDao<T, number>;

  constructor(context: common.Context) {
    this.context = context;
  }

  public async initDaoSession() {
    console.warn("[initDaoSession]")
    let daoSession = GlobalContext.getContext().getValue("daoSession");
    if (!daoSession) {
      this.helper = new SQLiteOpener(this.context, dbConfig.name);
      this.helper.setEncrypt(false);
      await this.helper.setVersion(dbVersion);
      this.helper.setEntities(User)

      // let migration = new Migration(dbConfig.name, Users.name, dbVersion).addColumn('created_at', ColumnType.strValue);
      // this.helper.setMigration(migration)

      let db: Database = await this.helper.getWritableDb();
      db.name = dbConfig.name;
      this.db = db;
      daoSession = new DaoMaster(db).newSession();
      GlobalContext.getContext().setValue("daoSession", daoSession);
    }
    this.daoSession = daoSession as DaoSession;
  }

  public getTableDao(): BaseDao<T, number> {
    return this.tableDao;
  }

  public setTableEntity(Table: any) {
    try {
      this.tableDao = this.daoSession.getBaseDao(Table);
    } catch (err) {
      throw new Error(err);
    }
  }

  public getQueryBuilder(): QueryBuilder<T> {
    if (!this.tableDao) {
      throw new Error("please set table entity first");
    }
    return this.tableDao.queryBuilder();
  }

  public getEntityClass(): Record<string, Object> {
    return GlobalContext.getContext().getValue(GlobalContext.KEY_CLS) as Record<string, Object>
  }

  public async insert(entity: T) {
    return await this.tableDao.insert(entity);
  }

  public async insertOrReplace(entity: T, setKeyAndAttach: boolean = true) {
    return await this.tableDao.insertOrReplace(entity, setKeyAndAttach);
  }

  public async update(entity: T, conflictResolution?: relationalStore.ConflictResolution) {
    return await this.tableDao.updateAsync(entity, conflictResolution)
  }
}